package ViewApplication;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.ValueMarker;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.time.DateRange;

import ModelApplication.Sound;
import UtilsApplication.HandleAudioUtil;
import UtilsApplication.WaveChartUtil;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.ImageIcon;

public class SoundWindow {

    private static int SLIDER_DEFAULT_VALUE = 100;
    private JFrame frame;
    private JPanel panel;
    private int lastValue;
    private JSlider slider;
    private ChartPanel chartPanel;
    private Sound sound;
    private JButton btnGraj;

    /**
     * Create the application.
     */
    public SoundWindow(Sound sound) {
        this.sound = sound;
        initialize();
        frame.setVisible( true );
        frame.setTitle( sound.getName() );
        
        JFreeChart chart = WaveChartUtil.plotWave( sound );
        XYPlot plot = (XYPlot)chart.getPlot();
        slider.addChangeListener(new ChangeListener() {
            
            private void zoomChartAxis(ChartPanel chartP, boolean increase){              
                int width = chartP.getMaximumDrawWidth() - chartP.getMinimumDrawWidth();
                int height = chartP.getMaximumDrawHeight() - chartP.getMinimumDrawWidth();       
                if(increase){
                    chartP.zoomInDomain(width/2, height/2);
                }else{
                    chartP.zoomOutDomain(width/2, height/2);
                }  
          }

            @Override
                public void stateChanged(ChangeEvent event) {
                    int value = slider.getValue();
                    
                    if(value < lastValue){
                        zoomChartAxis(chartPanel, false);
                    } else if (value > lastValue) {
                        zoomChartAxis(chartPanel, true);
                    }
                    lastValue = value;
                    
            }

        });
    
        
        
        plot.addRangeMarker(new ValueMarker(0,Color.BLACK,new BasicStroke(1)));

        chartPanel = new ChartPanel(chart);  
        Border border = BorderFactory.createCompoundBorder(
                BorderFactory.createEmptyBorder(4, 4, 4, 4),
                BorderFactory.createEtchedBorder()
            );
            chartPanel.setBorder(border);
        
        chartPanel.addMouseWheelListener(addZoomWheel());
        
        panel.add(chartPanel);
        JPanel dashboard = new JPanel(new BorderLayout());
        dashboard.setBorder(BorderFactory.createEmptyBorder(0, 4, 4, 4));   
        dashboard.add(slider);
        panel.add(dashboard, BorderLayout.SOUTH);
        
        btnGraj = new JButton("Graj");
        btnGraj.setIcon(null);
        btnGraj.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                playSound();
            }
        });
        dashboard.add(btnGraj, BorderLayout.EAST);
        
                
        frame.getContentPane().add((JPanel)panel, BorderLayout.CENTER);
        
        frame.pack();
    }
    
    public void setOnTheTop() {
        frame.setVisible( true );
        frame.toFront();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frame = new JFrame();
        frame.setBounds( 100, 100, 700, 600 );
        frame.getContentPane().setLayout(new BorderLayout(0, 0));
        
        panel = new JPanel();
        panel.setLayout(new BorderLayout());
        slider =  new JSlider(0, 200, SLIDER_DEFAULT_VALUE);
        lastValue=SLIDER_DEFAULT_VALUE;
        
    } 
    
    
    private MouseWheelListener addZoomWheel() {
        return new MouseWheelListener() {
            private void moveChart(boolean back) {
                NumberAxis domainAxis = (NumberAxis) ((XYPlot)chartPanel.getChart().getPlot()).getDomainAxis();
                double minimum = domainAxis.getRange().getLowerBound();
                double maximum = domainAxis.getRange().getUpperBound();
                double delta = (0.1f*(domainAxis.getRange().getLength()))*2;
                if (back) { // left
                    minimum = minimum - delta;
                    maximum = maximum - delta;
                } else { // right
                    minimum = minimum + delta;
                    maximum = maximum + delta;
                }
                DateRange range = new DateRange(minimum,maximum);
                domainAxis.setRange(range);
            }
            
            @Override
            public void mouseWheelMoved (MouseWheelEvent e) {
                if (e.getScrollType() != MouseWheelEvent.WHEEL_UNIT_SCROLL) return;
                if (e.getWheelRotation()< 0) moveChart(true);
                else                          moveChart(false);
            }
        };
    }
    
    private void playSound() {
        File w = new File("tmp.wav");
        HandleAudioUtil.saveAudio( sound, w  );
        Clip clip = null;
        try {
            clip = AudioSystem.getClip();
        } catch ( LineUnavailableException e ) {
            e.printStackTrace();
        }
        try {
            clip.open(AudioSystem.getAudioInputStream(w));
        } catch ( LineUnavailableException e ) {
            e.printStackTrace();
        } catch ( IOException e ) {
            e.printStackTrace();
        } catch ( UnsupportedAudioFileException e ) {
            e.printStackTrace();
        }
        clip.start();
    }
}
